package datasource.util;

import java.util.*;

public class Decoder {

	public static final short LZW = 5;

	public static ArrayList<Integer> encodeByteArrayList(
			ArrayList<byte[]> input, short compression_Method) {
		ArrayList<Integer> output = new ArrayList<Integer>();

		if (compression_Method == LZW) {
			// para todos los strips
			for (int i = 0; i < input.size(); i++) {
				ArrayList<String> temp = new ArrayList<String>();
				// variable String k
				String k;
				// indice para GetNextCharacter()
				int stringTableIndex = 0;
				ArrayList<String> stringTable = new ArrayList<String>();
				// inicializa la stringTable
				// InitializeStringTable();
				for (int j = 0; j < 255; j++) {
					stringTable.add(String.valueOf((char) j));
				}
				// WriteCode(ClearCode);
				// "\0\0"(dos caracteres nulos): codigo especial "limpio"
				// (ClearCode)
				temp.add("\0\0");
				// W = the empty string;
				// "" (String vacio)
				String omega = "";

				// para cada caracter en el strip
				for (int j = 0; j < input.get(i).length; j++) {
					// K = GetNextCharacter();
					k = stringTable.get(stringTableIndex);
					stringTableIndex++;
					// if W+K is in the string table
					if (stringTable.contains(new Integer(omega + k))) {
						omega += k;
					} else {

					}
				}
			}

		}
		return output;
	}
	 /** Decompress a list of output ks to a string. */
    public static byte[] decompress(byte[] currentStrip) {
        
    	// transforma el strip en una lista de bytes
		List<Integer> temp = new ArrayList<Integer>();
		for (int j = 0; j < currentStrip.length; j++) {
			// IMPORTANTE: EL METODO decompress recibe un arraylist
			// con enteros entre 0-255, pero tenemos un array de bytes
			// con rango -128 - 127, por lo tanto, se suma 255 si el
			// valor es
			// menor que 0
			temp.add(new Integer(currentStrip[j] + 128));
			//System.out.println(temp.get(j) + "<-----byte convertido "+ j);
		}
    	
    	// Construye el diccionario
        int dictSize = 256;
        System.out.println("Longitud comprimida "+temp.size());
        Map<Integer,String> dictionary = new HashMap<Integer,String>();
        for (int i = 0; i <= 255; i++)
            dictionary.put(i, "" + (char)i);
 
        String w = "" + (char)(int)temp.remove(0);
        String result = w;
        for (int k : temp) {
            String entry;
            if (dictionary.containsKey(k)){
                entry = dictionary.get(k);
            }
            else{
            	if (k == dictSize){
            		entry = w + w.charAt(0);
                }
            	 else
                     throw new IllegalArgumentException("k esta mal comprimido : " + k);
      
            }
            result += entry;
 
            // Add w+entry[0] to the dictionary.
            dictionary.put(dictSize++, w + entry.charAt(0));
 
            w = entry;
        }
        System.out.println("Longitud descomprimida "+result.length());
        return result.getBytes();
    }
 
    
    
    /** Compress a string to a list of output symbols. */
    public static List<Integer> compress2(String uncompressed) {
        // Build the dictionary.
        int dictSize = 256;
        Map<String,Integer> dictionary = new HashMap<String,Integer>();
        for (int i = 0; i < 256; i++)
            dictionary.put("" + (char)i, i);
 
        String w = "";
        List<Integer> result = new ArrayList<Integer>();
        for (char c : uncompressed.toCharArray()) {
            String wc = w + c;
            if (dictionary.containsKey(wc))
                w = wc;
            else {
                result.add(dictionary.get(w));
                // Add wc to the dictionary.
                dictionary.put(wc, dictSize++);
                w = "" + c;
            }
        }
 
        // Output the code for w.
        if (!w.equals(""))
            result.add(dictionary.get(w));
        return result;
    }
 
    /** Decompress a list of output ks to a string. */
    public static String decompress2(List<Integer> compressed) {
        // Build the dictionary.
        int dictSize = 256;
        Map<Integer,String> dictionary = new HashMap<Integer,String>();
        for (int i = 0; i < 256; i++)
            dictionary.put(i, "" + (char)i);
 
        String w = "" + (char)(int)compressed.remove(0);
        String result = w;
        for (int k : compressed) {
            String entry;
            if (dictionary.containsKey(k))
                entry = dictionary.get(k);
            else if (k == dictSize)
                entry = w + w.charAt(0);
            else
                throw new IllegalArgumentException("Bad compressed k: " + k);
 
            result += entry;
 
            // Add w+entry[0] to the dictionary.
            dictionary.put(dictSize++, w + entry.charAt(0));
 
            w = entry;
        }
        return result;
    }

}
